package com.ravi.service.impl;

import com.ravi.mapper.AreaInfoMapper;
import com.ravi.mapper.PatientMapper;
import com.ravi.model.entity.Patient;
import com.ravi.model.resp.AdminEndMsg;
import com.ravi.model.resp.AreaScreenMsg;
import com.ravi.model.resp.RoomScreenMsg;
import com.ravi.queue.StringQueueUtil;
import com.ravi.room.StringRoomUtil;
import com.ravi.service.intf.SendMsgService;
import com.ravi.websocket.WsEndpoint;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

@Service
public class SendMsgServiceImpl implements SendMsgService {

	@Autowired
	private StringQueueUtil stringQueueUtil;

	@Autowired
	private StringRoomUtil stringRoomUtil;

	@Autowired
	private PatientMapper patientMapper;

	@Autowired
	private AreaInfoMapper areaInfoMapper;


	@Override
	public void sendMsgToArea(String areaCode) {
		List<String> roomCodes = areaInfoMapper.getAreaRoomCodes(areaCode);
		Map<String, Object> areaMsg = getMultiRoomData(roomCodes);
		WsEndpoint.sendCheckMessage(areaMsg, areaCode);
	}

	private Map<String, Object> getMultiRoomData(List<String> roomCodes) {
		Map<String, Object> ret = new LinkedHashMap<>();
		for (String roomCode : roomCodes) {
			Map<String, Object> singleRoomData = getSingleRoomData(roomCode);
			ret.put(roomCode, singleRoomData);
		}
		return ret;
	}

	// 使用 message object 的新方法
	private RoomScreenMsg getRoomData(String roomCode) {
		RoomScreenMsg msg = new RoomScreenMsg();
		msg.setRoomCode(roomCode);
		// 排队数据ret + 队长length
		List<String> data = stringQueueUtil.getQueueData(roomCode);

		if (data.isEmpty()) { // 查不到
			msg.setQueue(new ArrayList<>());
			msg.setLength(Long.parseLong("0"));
		}else { // 查到了
			List<Patient> ret = new ArrayList<>();
			Long length = stringQueueUtil.getQueueLength(roomCode);
			for (String s : data) {
				ret.add(patientMapper.selectOneByCheckCode(s));
			}
			msg.setQueue(ret);
			msg.setLength(length);
		}

		// 检查数据
		String checkingPatient = stringRoomUtil.getCheckingPatient(roomCode);
		if (StringUtils.isEmpty(checkingPatient)) {
			msg.setChecking("暂无");
		} else {
			Patient patient = patientMapper.selectOneByCheckCode(checkingPatient);
			msg.setChecking(patient.toString());
		}

		// TODO: 下一诊室消息类的设计
		String next_check = "暂无"; // 某个RedisUtil从队列中取出队首
		if (StringUtils.isEmpty(next_check)) {
			msg.setNext_check("暂无");
		}else {
			msg.setNext_check(next_check);
		}

		return msg;
	}

	// 旧Api
	private Map<String, Object> getSingleRoomData(String roomCode) {
		Map<String, Object> r = new LinkedHashMap<>();
		// 排队数据ret + 队长length
		List<String> data = stringQueueUtil.getQueueData(roomCode);

		if (data.isEmpty()) { // 查不到
			r.put("queue", null);
			r.put("length", 0);
		}else { // 查到了
			List<Patient> ret = new CopyOnWriteArrayList<>();
			Long length = stringQueueUtil.getQueueLength(roomCode);
			for (String s : data) {
				ret.add(patientMapper.selectOneByCheckCode(s));
			}
			r.put("queue", ret);
			r.put("length", length);
		}

		// 检查数据
		String checkingPatient = stringRoomUtil.getCheckingPatient(roomCode);
		if (StringUtils.isEmpty(checkingPatient)) {
			checkingPatient = "暂无";
			r.put("checking", checkingPatient);
		} else {
			Patient patient = patientMapper.selectOneByCheckCode(checkingPatient);
			r.put("checking", patient);
		}

		// TODO: 下一诊室消息类的设计
		r.put("next_check", "暂无");

		return r;
	}

	@Override
	public void sendMsgToSameRoom(String roomCode) {
		RoomScreenMsg msg = getRoomData(roomCode);
		// 发送消息
		WsEndpoint.sendCheckMessage(msg, roomCode);
	}

	@Override
	public void sendMsgToRoomScreen(String roomCode) {
		RoomScreenMsg msg = getRoomData(roomCode);
		String clientname = roomCode + "screen";
		WsEndpoint.sendCheckMessage(msg, clientname);
	}

	private AreaScreenMsg getAreaScreenMsg(List<String> roomCodes) {
		AreaScreenMsg msg = new AreaScreenMsg();
		for (String roomCode : roomCodes) {
			RoomScreenMsg roomData = getRoomData(roomCode);
			msg.getAreaData().add(roomData);
		}
		return msg;
	}


	@Override
	public void sendMsgToAreaScreen(String areaCode) {
		List<String> roomCodes = areaInfoMapper.getAreaRoomCodes(areaCode);
		AreaScreenMsg msg = getAreaScreenMsg(roomCodes);
		WsEndpoint.sendCheckMessage(msg, areaCode);
	}

	private AdminEndMsg getAdminMsg() {
		AdminEndMsg msg = new AdminEndMsg();

		List<String> allAreas = areaInfoMapper.getAllAreas();
		for (String area : allAreas) {
			List<String> roomCodes = areaInfoMapper.getAreaRoomCodes(area);
			AreaScreenMsg areaScreenMsg = getAreaScreenMsg(roomCodes);
			msg.getGlobalData().put(area, areaScreenMsg);
		}
		return msg;
	}

	@Override
	public void sendMsgToAdminEnd() {
		AdminEndMsg msg = getAdminMsg();
		WsEndpoint.sendCheckMessage(msg, "admin");
	}
}
